package org.atlantis.grosbeak.lang;

import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;

import org.atlantis.grosbeak.lang.stream.StringOutputStream;

/**
 * 对于异常处理的帮助类。
 * 
 * @author <a href="mailto:seenoevil.cn@gmail.com">SeeNoEvil</a>
 * 
 */
public abstract class Exceptions {

	/**
	 * 把一系列的异常装入到异常集合类中。
	 * 
	 * @param es
	 * @return
	 */
	public static UniteException unite(Throwable... es) {
		UniteException ue = new UniteException();
		for (Throwable e : es)
			ue.add(e);
		return ue;
	}

	/**
	 * 一个没有实现的运行时异常。
	 * 
	 * @return
	 */
	public static RuntimeException noImplement() {
		return new RuntimeException("Not implement yet!");
	}

	/**
	 * 通过格式化字符串，生成运行时异常。
	 * 
	 * @param format
	 * @param args
	 * @return
	 */
	public static RuntimeException makeThrow(String format, Object... args) {
		return new RuntimeException(String.format(format, args));
	}

	/**
	 * 通过格式化字符串，生成指定类型的异常。
	 * 
	 * @param <T>
	 * @param clazz
	 * @param format
	 * @param args
	 * @return
	 */
	public static <T extends Throwable> T makeThrow(Class<T> clazz,
			String format, Object... args) {
		return Mirror.me(clazz).fruit(String.format(format, args));
	}

	/**
	 * 通过格式化字符串，生成指定类型的异常。
	 * 
	 * @param <T>
	 * @param clazz
	 * @param e
	 * @param format
	 * @param args
	 * @return
	 */
	public static <T extends Throwable> T makeThrow(Class<T> clazz,
			Throwable e, String format, Object... args) {
		return Mirror.me(clazz).fruit(String.format(format, args), e);
	}

	/**
	 * 将抛出的异常封装成运行时异常，并添加自定义描述。
	 * 
	 * @param e
	 * @param format
	 * @param args
	 * @return
	 */
	public static RuntimeException wrapThrow(Throwable e, String format,
			Object... args) {
		return new RuntimeException(String.format(format, args), e);
	}

	/**
	 * 把一个异常对象封装成运行时异常，如果异常对象本来就是运行时异常就直接返回。
	 * 如果是InvocationTargetException，那么就取出其中的TargetException然后进行封装。
	 * 
	 * @param e
	 * @return
	 */
	public static RuntimeException wrapThrow(Throwable e) {
		if (e instanceof RuntimeException)
			return (RuntimeException) e;
		if (e instanceof InvocationTargetException)
			return wrapThrow(((InvocationTargetException) e)
					.getTargetException());
		return new RuntimeException(e);
	}

	/**
	 * 用一个指定类型的异常来包裹一个抛出的异常。
	 * 
	 * @param <T>
	 * @param clazz
	 * @param e
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T extends Throwable> T wrapThrow(Class<T> clazz, Throwable e) {
		if (clazz.isAssignableFrom(e.getClass()))
			return (T) e;
		return Mirror.me(clazz).fruit(e);
	}

	/**
	 * 将一个异常的异常堆栈表示成一个字符串。
	 * 
	 * @param e
	 * @return
	 */
	public static String getStackTrace(Throwable e) {
		StringBuilder sb = new StringBuilder();
		StringOutputStream sos = new StringOutputStream(sb);
		PrintStream ps = new PrintStream(sos);
		e.printStackTrace(ps);
		ps.flush();
		return sos.get().toString();
	}
}
